package c.c.d.s.s.o.c.as.boot;

import c.c.d.s.s.o.c.as.domain.client.dto.ResourceAddressClientAccessScopeMapping;
import c.c.d.s.s.o.c.as.domain.client.dto.ResourceAddressClientAuthorityMapping;
import c.c.d.s.s.o.c.as.domain.user.dto.ResourceAddressUserAuthorityMapping;
import c.c.d.s.s.o.c.as.repository.client.ClientAccessScopeMapper;
import c.c.d.s.s.o.c.as.repository.client.ClientAuthorityMapper;
import c.c.d.s.s.o.c.as.repository.user.UserAuthorityMapper;
import cn.caplike.data.redis.service.spring.boot.starter.RedisKey;
import cn.caplike.data.redis.service.spring.boot.starter.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.stream.Collectors;

/**
 * Description: 资源地址元数据初始化<br>
 * Details: 授权服务器启动的时候, 从数据源里加载访问控制香瓜你的元数据, 并放入缓存. 供资源服务器调用
 *
 * @author LiKe
 * @version 1.0.0
 * @date 2020-08-03 14:33
 */
@Order(1)
@Slf4j
@Component
public class ResourceAddressMetadataInitializer implements ApplicationRunner {

    /**
     * metadata.resource-address 缓存前缀
     */
    private static final String CACHE_PREFIX_METADATA_RESOURCE_ADDRESS = "authorization-server.metadata.resource-address";

    private RedisService redisService;

    // ~ ResourceAddress Mappers
    // -----------------------------------------------------------------------------------------------------------------

    private ClientAccessScopeMapper clientAccessScopeMapper;

    private ClientAuthorityMapper clientAuthorityMapper;

    private UserAuthorityMapper userAuthorityMapper;

    // =================================================================================================================

    @Override
    public void run(ApplicationArguments args) {
        log.info("Resource address metadata initializing ...");

        final RedisService.Hash redisServiceOpsForHash = redisService.hash();

        redisServiceOpsForHash.putAll(
                RedisKey.builder().prefix(CACHE_PREFIX_METADATA_RESOURCE_ADDRESS).suffix(ResourceAddressClientAccessScopeMapping.CACHE_SUFFIX).build(),
                clientAccessScopeMapper.composeResourceAddressClientAccessScopeMapping().stream().collect(Collectors.toMap(
                        ResourceAddressClientAccessScopeMapping::getResourceAddress,
                        ResourceAddressClientAccessScopeMapping::getClientAccessScopeName
                ))
        );
        log.debug("==============================================================================");
        log.debug("|            Metadata: ResourceAddress - ClientAccessScope Cached            |");
        log.debug("==============================================================================");

        redisServiceOpsForHash.putAll(
                RedisKey.builder().prefix(CACHE_PREFIX_METADATA_RESOURCE_ADDRESS).suffix(ResourceAddressClientAuthorityMapping.CACHE_PREFIX).build(),
                clientAuthorityMapper.composeResourceAddressClientAuthorityMapping().stream().collect(Collectors.toMap(
                        ResourceAddressClientAuthorityMapping::getResourceAddress,
                        ResourceAddressClientAuthorityMapping::getClientAuthorityName
                ))
        );
        log.debug("==============================================================================");
        log.debug("|             Metadata: ResourceAddress - ClientAuthority Cached             |");
        log.debug("==============================================================================");

        redisServiceOpsForHash.putAll(
                RedisKey.builder().prefix(CACHE_PREFIX_METADATA_RESOURCE_ADDRESS).suffix(ResourceAddressUserAuthorityMapping.CACHE_PREFIX).build(),
                userAuthorityMapper.composeResourceAddressUserAuthorityMapping().stream().collect(Collectors.toMap(
                        ResourceAddressUserAuthorityMapping::getResourceAddress,
                        ResourceAddressUserAuthorityMapping::getUserAuthorityName
                ))
        );
        log.debug("==============================================================================");
        log.debug("|              Metadata: ResourceAddress - UserAuthority Cached              |");
        log.debug("==============================================================================");

        log.info("Resource address metadata initialized.");
    }

    // ~ Autowired
    // -----------------------------------------------------------------------------------------------------------------

    @Autowired
    public void setRedisService(RedisService redisService) {
        this.redisService = redisService;
    }

    @Autowired
    public void setClientAccessScopeMapper(ClientAccessScopeMapper clientAccessScopeMapper) {
        this.clientAccessScopeMapper = clientAccessScopeMapper;
    }

    @Autowired
    public void setClientAuthorityMapper(ClientAuthorityMapper clientAuthorityMapper) {
        this.clientAuthorityMapper = clientAuthorityMapper;
    }

    @Autowired
    public void setUserAuthorityMapper(UserAuthorityMapper userAuthorityMapper) {
        this.userAuthorityMapper = userAuthorityMapper;
    }
}
